#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>

void f(std::string_view v) {
  std::cout << "string view just pointer + length, like golang slice.\n";
  std::cout << "string_view: " << v << "\n";
}

std::vector<std::string> split(const std::string &str, char delimeter) {

  std::string s = str; // copy string
  std::vector<std::string> out;

  size_t pos = 0;

  while ((pos = s.find(delimeter)) != std::string::npos) {
    std::string token = s.substr(0, pos);
    out.emplace_back(token); // move to out
    s.erase(0, pos + 1);     // remove token and jump delimeter
  }

  out.emplace_back(s);

  return out;
}

std::vector<std::string> split_by_getline(const std::string &str,
                                          char delimeter) {

  std::vector<std::string> out;

  std::istringstream is(str);

  std::string token;

  while (std::getline(is, token, delimeter)) {
    out.emplace_back(token);
  }

  return out;
}

template <char delimeter> class String : public std::string {
  friend std::istream &operator>>(std::istream &is, String &out) {
    std::getline(is, out, delimeter);
    return is;
  }
};

int main(int argc, char *argv[]) {
  // string(size_t n, char c)
  std::string a(1, 'a');

  std::cout << "a is:" << a << "\n";

  std::string s;

  s += 'a';

  std::cout << "s is:" << s << "\n";

  s = 'a';

  std::cout << "s is:" << s << "\n";

  char cstr[] = "hello cstr";
  std::string str = cstr;

  std::cout << "from cstr is: " << str << "\n";

  std::string line = "abc,def,ghi";

  //  std::vector<std::string> out = split(line, ',');

  // impl by istream
  // std::istringstream iss(line);

  // std::vector<std::string> out((std::istream_iterator<String<','>>(iss)),
  //                             std::istream_iterator<String<','>>());

  // impl by getline
  std::vector<std::string> out = split_by_getline(line, ',');
  for (const auto &c : out) {
    std::cout << c << "\n";
  }

  const std::string hello = "how are you today?";

  f(hello);

  return 0;
}
